package com.uroad.jilinpda.common;

import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;


import com.uroad.jilinpda.bleactivation.Tlv;
import com.uroad.jilinpda.bleactivation.TlvUtils;
import com.uroad.jilinpda.util.LogUtils;
import com.uroad.jilinpda.util.ObuKeepAlive;
import com.uroad.jilinpda.util.PriorityExecutor;
import com.uroad.jilinpda.util.SPEC;
import com.uroad.jilinpda.util.SPUtils;
import com.uroad.jilinpda.util.SdkHelper;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TimeZone;

import etc.obu.data.CardInformation;
import etc.obu.data.ObuSystemInformation;

/**
 * @创建者 wlw
 * @创建时间 2019/9/3 11:17
 * @描述
 */
public class Base58ETCActivity extends BaseActivity implements Cmd,Code{
    private static final String LOG_TAG="OBUCmdUtil";
    //执行状态
    protected SPEC.EVENT mResultCode = SPEC.EVENT.IDLE;

    //DSRC通道相关定义
    //通道类型：DSRC模块通道
    public static final int CHANNEL_TYPE_DSRC = 0;
    //DSRC模块13.56M通道ID，sdk指定为0，可直接操作IC卡
    public static final int DSRC_CHANNEL_ICC = 0;
    //DSRC模块SAM卡通道， 1~4: sam1~sam4，通过配置文件直接读取通道的ID，此处不进行定义

    //通道类型：OBU通道
    public static final int CHANNEL_TYPE_OBU = 1;
    //OBU IC卡通道，sdk指定为1
    public static final int OBU_CHANNEL_ICC = 1;
    //OBU ESAM通道，sdk指定为2
    public static final int OBU_CHANNEL_ESAM = 2;
    protected CardInformation tmpCardInformation;
    protected ObuSystemInformation obuSystemInformation;
    protected ObuKeepAlive keepAlive;
    //是否开始保活
    protected boolean isKeepAlive = false;
    //是否单卡操作 不经过obu直接操作卡片
    protected boolean isSingleCard = false;
    protected static int cardSlot;
    protected static String fileName;
    protected static String fileBasePath = Environment.getExternalStorageDirectory().getPath()+"/lnM700log/";
    protected static String filePath;
    protected SimpleDateFormat logFormat = new SimpleDateFormat("_yyyy_MM_dd");
    protected SimpleDateFormat logFormats = new SimpleDateFormat("HH:mm:ss:SSS");
    protected static String channelType;
    protected static long difference;
    protected static long lastTime;
    protected static String tollName;
    private SdkHelper sdkhelper;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        keepAlive = ObuKeepAlive.getInstance();
        sdkhelper = SdkHelper.getInstance(this);
        initLogFile();
    }

    /**
     * 初始化日志时间
     */
    protected void initLogFile() {
        difference = (long) SPUtils.get(this, GlobalData.sp_difference, 0L);
        tollName = (String) SPUtils.get(this, GlobalData.spTollName, "");
        logFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        logFormats.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        fileName = "lnm700log" + tollName + logFormat.format(System.currentTimeMillis() + difference) +"_"+ Build.SERIAL + ".txt";
        filePath = fileBasePath + fileName;
    }

    @Override
    protected void onResume() {
        super.onResume();
        cardSlot = (int) SPUtils.get(this, GlobalData.spCardSlot, 3);
    }

    public void setSingleCard(boolean singleCard) {
        isSingleCard = singleCard;
    }

    /**
     * cpu发送apdu组合指令
     *
     * @param channelID    通道号， 1 ICC 2 ESAM
     * @param instructions 组合指令 如选择1001目录加读取0015文件加读取卡余额 8017810700A40000021001020500B095002B0305805C000204
     * @return 组合指令
     */
    protected void cpuSendTLVCmd(final int tag, final int channelID, final String instructions, final OnResultListener onResultListener) {
        PriorityExecutor.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                LogUtils.i("====================CMD开始发送组合指令：====================\n" + instructions);
                List<Tlv> instructionsLists = TlvUtils.getSendTlv(instructions);
                String[] cmds = new String[instructionsLists.size()];
                boolean[] isNeedExecuteNexts = new boolean[instructionsLists.size()];
                for (int i = 0; i < instructionsLists.size(); i++) {
                    Tlv tlv = instructionsLists.get(i);
                    cmds[i] = tlv.getValue();
                    isNeedExecuteNexts[i] = TlvUtils.isNeedExecuteNextByTag(tlv.getTag());
                }
                List<String> respInstructionsLists = transceiveData(channelID,false, cmds, isNeedExecuteNexts, onResultListener);
                if (respInstructionsLists.size() > 0) {
                    final String tlvData = TlvUtils.getRespTlvString(respInstructionsLists, instructionsLists);
                    LogUtils.i("CMD组合指令返回数据:" + tlvData);
                    if (!TextUtils.isEmpty(tlvData)) {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                onResultListener.onSuccess(tag, mResultCode, tlvData);
                            }
                        });
                    }
                }else {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            onResultListener.onError("");
                        }
                    });
                }
            }
        });
    }

    /**
     * 发送指令集
     * @param cmds 指令集
     * @param isNeedExecuteNexts 出错时是否需要执行下一段指令 因改为交由接口判断故省去判断
     * @return 返回指令集合
     */
    protected List<String> transceiveData(int channelID,boolean isPsam, String[] cmds, boolean[] isNeedExecuteNexts,OnResultListener onResultListener) {
        List<String> respInstructionsLists = new ArrayList<String>();
        int result = obuCosChannel(channelID, isPsam, cmds, onResultListener);
        if (result == 0&&!TextUtils.isEmpty(cmds[0])) {
            for (String cmdResult : cmds) {
                respInstructionsLists.add(cmdResult);
            }
            mResultCode = SPEC.EVENT.SUCCESS;
        }else{
            mResultCode = SPEC.EVENT.ERROR;
        }
        return respInstructionsLists;
    }

    /**
     * 发送单条纯cos指令（不用组合）
     * @param tag 标签tag
     * @param channelID 通道号， 1 ICC 2 ESAM
     * @param cmd 需要发送的单条指令
     * @param onResultListener 回调
     */
    protected void sendSingleCmd(final int tag, final boolean ispsam, final int channelID, final String cmd, final OnResultListener onResultListener) {
//        PriorityExecutor.getInstance().execute(new Runnable() {
//            @Override
//            public void run() {
                String[] cmds = new String[]{cmd};
                int result = obuCosChannel(channelID, ispsam, cmds, onResultListener);
                if (result == 0) {
                    onResultListener.onSuccess(tag, mResultCode, cmds[0]);
                } else {
                    onResultListener.onError("tag:" + tag + "\ncmd:" + cmd);
                }
//                return cmds[0];
//            }
//        });
    }
    protected void getOBUNo(final OnResultListener resultListener){
        PriorityExecutor.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    //打开天线
                    int result = CurrApplication.getInstance().openDsrc();
                    LogUtils.i("CMD打开天线："+result);
                    if (result == 0) {
                        Thread.sleep(200);//缓冲
                        CardInformation tmpCardInformation = new CardInformation();
                        final ObuSystemInformation obuSystemInformation = new ObuSystemInformation();
                        //搜索obu 获取系统信息 车辆信息
                        result = CurrApplication.getInstance().getHandsetSDK().findObu(obuSystemInformation, tmpCardInformation);
                        if (result == 0) {
                            Base58ETCActivity.this.tmpCardInformation = tmpCardInformation;
                            Base58ETCActivity.this.obuSystemInformation = obuSystemInformation;
                            mResultCode = SPEC.EVENT.SUCCESS;
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    resultListener.onSuccess(CMD_A5, mResultCode, obuSystemInformation.getSerialNumber());
                                    keepAlive.start();
                                    isKeepAlive = true;

                                }
                            });
                        } else {
                            mResultCode = SPEC.EVENT.ERROR;
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    resultListener.onError("搜索设备失败");
                                }
                            });
                        }
                    }
                    //                    CurrApplication.getInstance().getHandsetSDK().obuRelease(false, true);
                } catch (Exception e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            resultListener.onError("搜索设备异常");
                        }
                    });
                }
                //                CurrApplication.getInstance().closeDsrc();
                //                obuKeepAlive();
            }
        });
    }

    //    /**
    //     * 获取OBU
    //     * @param resultListener
    //     */
    //    protected void findObu(final OnResultListener resultListener){
    //        PriorityExecutor.getInstance().execute(new Runnable() {
    //            @Override
    //            public void run() {
    //                try {
    //                    int result = CurrApplication.getInstance().openDsrc();
    //                    if (result >= 0) {
    //                        tmpCardInformation = new CardInformation();
    //                        obuSystemInformation = new ObuSystemInformation();
    //                        result = CurrApplication.getInstance().getHandsetSDK().findObu(obuSystemInformation, tmpCardInformation);
    //                        if (result == 0) {
    //                            mResultCode = SPEC.EVENT.SUCCESS;
    //                            resultListener.onSuccess(CMD_FINDOBU, mResultCode, obuSystemInformation.getSerialNumber());
    //                        } else {
    //                            mResultCode = SPEC.EVENT.ERROR;
    //                            resultListener.onError("搜索设备失败");
    //                        }
    //                    }
    //                    CurrApplication.getInstance().getHandsetSDK().obuRelease(false, true);
    //                } catch (Exception e) {
    //                    e.printStackTrace();
    //                    resultListener.onError("搜索设备失败");
    //                }
    //                //                obuKeepAlive();
    //                CurrApplication.getInstance().closeDsrc();
    //            }
    //        });
    //    }

    /**
     *
     * @Title judgeCosRspStatus
     * @Description 判断cos指令执行状态码
     * @author ZengXiaoJiang
     * @param num cos指令返回的条数
     * @param cosRsps 输出cos指令返回的数据，不包括2个字节的状态码
     * @return
     * int : 0成功，非0失败
     */
    private int judgeCosRspStatus(int num, String[] cosRsps) {
        for(int i = 0; i < num; i++){
            Log.i(LOG_TAG, String.format("cosRsps[%d]: %s", i, cosRsps[i]));
            String cosRspStatus = cosRsps[i].substring(cosRsps[i].length()- 4, cosRsps[i].length());
            if (!cosRspStatus.equals("9000")) {
                Log.i(LOG_TAG, "judgeCosRspStatus, cos response status code: " + cosRspStatus);
                return -1;
            }
        }

        return 0;
    }

    //    /**
    //     *
    //     * @Title cosChannel
    //     * @Description cos指令通道
    //     * @author ZengXiaoJiang
    //     * @param channelType 通道类型，DSRC模块：CHANNEL_TYPE_DSRC， OBU模块：CHANNEL_TYPE_OBU
    //     * @param channelID DSRC通道：0-ICC通道，1-SAM1，2-SAM2, 3-SAM3，4-SAM4；OBU通道：1-ICC，2-ESAM
    //     * @param num cos指令条数
    //     * @param commands 存放cos指令的String数组，改参数同时输出执行cos指令后返回的String数组
    //     * @return
    //     * int : 0成功，非0失败
    //     */
    //    public int cosChannel(int channelType, int channelID, int num, String[] commands){
    //        int ret = -1;
    //        Log.e(LOG_TAG, "channelType = " + channelType + " ChannelID = " + channelID);
    //        for(int i = 0; i < 2; i++){
    //            for (int j = 0; j < num; j++) {
    //                String rsp = String.format("cosChannel, commands[%d]: %s", j, commands[j]);
    //                Log.e(LOG_TAG, rsp);
    //            }
    //
    //            switch (channelType) {
    //                case CHANNEL_TYPE_DSRC: //dsrc模块通道
    //                    ret = CurrApplication.getInstance().getHandsetSDK().dsrcCosCommand((byte)channelID, num, commands);
    //                    break;
    //
    //                case CHANNEL_TYPE_OBU:	//obu通道
    //                    ret = CurrApplication.getInstance().getHandsetSDK().obuCosCommand((byte)channelID, num, commands);
    //                    break;
    //
    //                default:
    //                    break;
    //            }
    //
    //            if (ret == 0) {
    //                //判断cos执行状态码 因交由接口判断 故省去本地判断
    //                //                ret = this.judgeCosRspStatus(num, commands);
    //                break;
    //            }else{
    //                Log.e(LOG_TAG, "cosChannel return:" + ret);
    //                ret = -1;
    //                Log.e(LOG_TAG, "cosChannel failed, try again");
    //                return ret;
    //            }
    //        }
    //
    //        return ret;
    //    }

    /**
     *
     * @Title obucosChannel
     * @Description 发送cos指令
     * @author wlw
     * @param channelID 通道号， 1 ICC 2 ESAM
     * @param isPsam 是否psam卡
     * @param mCosCmds 存放cos指令的String数组，改参数同时输出执行cos指令后返回的String数组
     * @param onResultListener
     * @return
     * int : 0成功，非0失败
     */
    public int obuCosChannel(int channelID,boolean isPsam, final String[] mCosCmds, final OnResultListener onResultListener) {
        int result = -1;
        if (isKeepAlive) {
            keepAlive.setTaskStatus(1);
            int tryTimes = 40;
            while(true) {
                tryTimes--;
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (keepAlive.getTaskStatus() == 2) {
                    break;
                }
                if (tryTimes < 1) {
                    break;
                }
            }
            keepAlive.stop();
            isKeepAlive = false;
            LogUtils.i("CMD保活结束");
        }
        if (isPsam) {
            channelType = "PSAM";
        }else{
            channelType = channelID == 1 ? "ICC" : "ESAM";
        }
//        RandomAccessFile raf = null;
        try {
            //创建文件夹及文件
//            File file = FileUtils.makeFilePath(fileBasePath, fileName);
//            raf = new RandomAccessFile(file, "rwd");
//            raf.seek(file.length());//跳转到文件末尾

            String[] cmds = new String[1];
            for (int i = 0; i < mCosCmds.length; i++) {
                cmds[0] = mCosCmds[i];
                LogUtils.i("CMD指令发送：" + cmds[0]);
//                raf.write((logFormats.format(System.currentTimeMillis()+difference) + "-" + channelType + "-发送：" + cmds[0] + "\r\n").getBytes());
                if (isPsam) {
                    result = CurrApplication.getInstance().getHandsetSDK().dsrcCosCommand(cardSlot, 1, cmds);
                }else if (isSingleCard) {
                    result = CurrApplication.getInstance().getHandsetSDK().dsrcCosCommand(0, 1, cmds);
                }else {
                    result = CurrApplication.getInstance().getHandsetSDK().obuCosCommand(channelID, 1, cmds);
                }
                LogUtils.i("执行码：" + result);
                long nowTime = System.currentTimeMillis()+difference;
//                raf.write((logFormats.format(nowTime) + "-" + channelType + "-执行：" + result +" 耗时"+(nowTime - lastTime)+ "\r\n").getBytes());
                lastTime = nowTime;
                if (result == 0) {
                    LogUtils.i("返回数据：" + cmds[0]);
//                    raf.write((logFormats.format(nowTime) + "-" + channelType + "-返回：" + cmds[0] +" 耗时"+(nowTime - lastTime)+ "\r\n").getBytes());
                    mCosCmds[i] = cmds[0];
                    lastTime = nowTime;
//                    Thread.sleep(200);
                } else {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            onResultListener.onError("发卡失败");
                        }
                    });
                    break;
                }
            }
//            raf.close();
//            if (isSingleCard) {
//                keepAlive.setChannelID(2);
//            }else{
//                keepAlive.setChannelID(1);
//            }
            if (!isPsam && !isSingleCard) {//写OBU才需要保活 贴ETC和CPC卡不用
                keepAlive.start();
                isKeepAlive = true;
                sdkhelper.setNeedAlive(true);
            }else{
                sdkhelper.setNeedAlive(false);
            }
            LogUtils.i("CMD开始保活");
        } catch (Exception e) {
            e.printStackTrace();
//            if (raf != null) {
//                try {
//                    raf.close();
//                } catch (IOException ex) {
//                    ex.printStackTrace();
//                }
//            }
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    onResultListener.onError("执行异常");
                }
            });
        }
        return result;
    }

    /**
     * 释放OBU资源
     */
    protected void obuRelease(){
        CurrApplication.getInstance().getHandsetSDK().obuRelease(false, true);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (isFinishing()) {
            stopObuKeepAlive();
//            CurrApplication.getInstance().closeDsrc();
        }
    }


    /**
     * 标签保活
     */
    public void obuKeepAlive(){
        //标签保活
        keepAlive.setObuPorviderCode(obuSystemInformation.getObuId());
        keepAlive.start();
    }

    protected void stopObuKeepAlive(){
//        PriorityExecutor.getInstance().execute(new Runnable() {
//            @Override
//            public void run() {
        sdkhelper.setNeedAlive(false);
        if (isKeepAlive) {
            keepAlive.setTaskStatus(1);
            int tryTimes = 40;
            while(true) {
                tryTimes--;
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (keepAlive.getTaskStatus() == 2) {
                    break;
                }
                if (tryTimes < 1) {
                    break;
                }
            }
            keepAlive.stop();
            isKeepAlive = false;
            LogUtils.i("CMD保活结束");
        }
//                if (!isSingleCard) {
//                    keepAlive.setChannelID(1);
//                    obuRelease();
//                }
//                CurrApplication.getInstance().closeDsrc();
//            }
//        });
    }

    //        private GvWebResult changeObuKey(int type,
    //                                         String listNo,
    //                                         String file,
    //                                         String arithmetic,
    //                                         String auth) {
    //            //获取4字节随机数
    //            String[] random = new String[1];
    //            GvWebResult result = getObuRandom(random);
    //            if (result.getRet() != 0) {
    //                return result;
    //            }
    //            //标签保活 每100毫秒发送一次 选择1001目录指令
    //            ObuKeepAlive keepAlive = new ObuKeepAlive(sdk);
    //            keepAlive.setObuPorviderCode(systemInformation.getObuId());
    //            keepAlive.start();
    //            log.info("Start keeping obu alive!");
    //            //在线获取更新MF主控密钥，返回：24字节密文 + 4字节MAC
    //            String[] key = new String[1];
    //            result = getKey(listNo, random[0], file, arithmetic, auth, key);
    //            //以获取到接口返回 等待保活指令执行完成
    //            // （taskStatus=0才会发送指令 发完会判断taskStatus是否为0 不为0则把taskStatus变为2
    //            // 所以这里把taskStatus设置为1 实际是为了不再发送指令 等待指令执行完成 taskStatus变为2）
    //            keepAlive.setTaskStatus(1);
    //            int tryTimes = 40;
    //            while(true) {
    //                tryTimes--;
    //                try {
    //                    Thread.sleep(50);
    //                } catch (InterruptedException e) {
    //                    e.printStackTrace();
    //                }
    //
    //                if (keepAlive.getTaskStatus() == 2) {
    //                    log.info("keep obu alive, getTaskStatus = 2, break while!");
    //                    break;
    //                }
    //
    //                if (tryTimes < 1) {
    //                    log.info("keep obu alive, waiting finish keepAlive task timeout, break while!");
    //                    break;
    //                }
    //            }
    //            keepAlive.stop();
    //            log.info("Stop keeping obu alive!");
    //            if (result.getRet() != WebResultCode.SUCCESS) {
    //                return result;
    //            }
    //
    //            //本地替换MF主控密钥
    //            if (type == 0) {
    //                result = changeKey(key[0]);
    //            } else {
    //                result = changeOtherKey(key[0]);
    //            }
    //            if (result.getRet() != 0) {
    //                return result;
    //            }
    //            return result;
    //        }


    @Override
    public void doRequestAuth(String methodUrl, HashMap<String, Object> params, String id) {
        super.doRequestAuth(methodUrl, params, id);
        long nowTime = System.currentTimeMillis() + difference;
//        writeLogInfo((logFormats.format(nowTime) + "-request-url:" + methodUrl + "\r\n" +
//                "入参：" + params.toString() +" 耗时"+(nowTime - lastTime)+ "\r\n").getBytes());
        lastTime = nowTime;
    }

    @Override
    public void doPost(String url, HashMap<String, Object> params, String id) {
        super.doPost(url, params, id);
        long nowTime = System.currentTimeMillis() + difference;
//        writeLogInfo((logFormats.format(nowTime) + "-request-url:" + url + "\r\n" +
//                "入参：" + params.toString() +" 耗时"+(nowTime - lastTime)+ "\r\n").getBytes());
        lastTime = nowTime;
    }

    @Override
    public void OnHttpTaskComplete(String result, String id) {
        super.OnHttpTaskComplete(result, id);
        long nowTime = System.currentTimeMillis() + difference;
//        writeLogInfo((logFormats.format(nowTime) + "-request-url:" + id + "\r\n" +
//                "出参：" + result +" 耗时"+(nowTime - lastTime)+ "\r\n").getBytes());
        lastTime = nowTime;
    }

    @Override
    public void OnHttpFailure(String id, String msg) {
        super.OnHttpFailure(id, msg);

    }

   /* public void writeLog(String str){
        writeLogInfo((str+ "--------------------------------------------->\r\n").getBytes());
    }*/
    /**
     * 写日志
     * @param content
     */
    /*public void writeLogInfo(byte[] content) {
        RandomAccessFile raf = null;
        try {
            //创建文件夹及文件
            File file = FileUtils.makeFilePath(fileBasePath, fileName);
            raf = new RandomAccessFile(file, "rwd");
            raf.seek(file.length());//跳转到文件末尾
            raf.write(content);//写入日志
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                raf.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }*/

    public interface OnResultListener{
        /**
         * 读取回调监听，回调均在主线程
         *
         * @param requestCode 请求调用code，用于回调标记
         * @param event       响应情况
         * @param result         正确返回相应数据。错误时，返回错误内容。
         */
        void onSuccess(int requestCode, SPEC.EVENT event, String result);
        void onError(String error);
    }
}
